#include "analysis.h"

//判断函数头并更新命令标记类型
int chooseCommand(const char* p,Canalysis_t* anaCommand){
    
    /* printf("chooseCommand is %s\n",p); */
    
    int ret = -1;
    ret = strcmp(p,"cd");
    if(ret == 0){
        anaCommand->flag = FLAG_CD;
        /* anaCommand->offset = 3; */
        /* printf("cd success\n"); */
        return 0;
    }
    ret = strcmp(p,"ls");
    if(ret == 0){
        anaCommand->flag = FLAG_LS;
        /* anaCommand->offset = 3; */
        /* printf("ls success\n"); */
        return 0;
    }
    ret = strcmp(p,"pwd");
    if(ret == 0){
        anaCommand->flag = FLAG_PWD;
        /* anaCommand->offset = 4; */
        return 0;
    }
    ret = strcmp(p,"mkdir");
    if(ret == 0){
        anaCommand->flag = FLAG_MKDIR;
        /* anaCommand->offset = 6; */
        return 0;
    }
    ret = strcmp(p,"rmdir");
    if(ret == 0){
        anaCommand->flag = FLAG_RMDIR;
        /* anaCommand->offset = 6; */
        return 0;
    }
    ret = strcmp(p,"gets");
    if(ret == 0){
        anaCommand->flag = FLAG_GETS;
        /* anaCommand->offset = 6; */
        return 0;
    }
    ret = strcmp(p,"puts");
    if(ret == 0){
        anaCommand->flag = FLAG_PUTS;
        /* anaCommand->offset = 6; */
        return 0;
    }
    ret = strcmp(p,"remove");
    if(ret == 0){
        anaCommand->flag = FLAG_REMOVE;
        /* anaCommand->offset = 6; */
        return 0;
    }
    return -1;
}

//业务实现，传入已经完成的栈命令，传入传出结果
int cdDir(const char* command,Canalysis_t* anaCommand){
    int ret = chdir(command);
    bzero(anaCommand->clientCommand,anaCommand->commandLength);
    if(ret == -1){
        strerror_r(errno,anaCommand->clientCommand,anaCommand->commandLength);
        /* printf("erro message is %s\n",anaCommand->clientCommand); */
        return -1;
    }
    if (getcwd(anaCommand->clientCommand, anaCommand->commandLength) == NULL) {
        snprintf(anaCommand->clientCommand, anaCommand->commandLength, "获取路径失败");
        return -1;
    }
    return 0;
}

int lsDir(const char* command,Canalysis_t* anaCommand){
    printf("lsdit func into\n");
    bzero(anaCommand->clientCommand,anaCommand->commandLength);
    DIR *dir = opendir(command);
    if(dir == NULL){
        strerror_r(errno,anaCommand->clientCommand,anaCommand->commandLength);
        /* printf("erro message is %s\n",anaCommand->clientCommand); */
        return -1;
    }
    /* printf("opendir successful\n"); */
    
    struct dirent *entry;
    int size = 0;
    while ((entry = readdir(dir)) != NULL) {  // 逐项读取
        sprintf(anaCommand->clientCommand+size,"%s ",entry->d_name);// 打印文件名/子目录名
        size += strlen(entry->d_name)+1;           
    }
    anaCommand->clientCommand[size-1] = '\0';
    closedir(dir);
    return 0;
}

int pwdDir(const char* command,Canalysis_t* anaCommand){
    char buffer[1024] = {0};
    bzero(anaCommand->clientCommand,anaCommand->commandLength);
    if (getcwd(buffer,sizeof(buffer)) == NULL) {
        snprintf(anaCommand->clientCommand, anaCommand->commandLength, "获取路径失败");
        return -1;
    }
    /* printf("buffer is %s\n",buffer); */
    sprintf(anaCommand->clientCommand,"home%s",buffer+anaCommand->homelength);
    /* strcpy(anaCommand->clientCommand,buffer+anaCommand->homelength); */
    return 0;
}

int mkdir_p(const char* path){
    char temp[1024] = {0};
    char* p = NULL;
    size_t len;

    sprintf(temp,"%s",path);
    len = strlen(temp);

    //去除末尾的/，如果有的話
    if(temp[len-1] == '/'){
        temp[len-1] = '\0';
    }

    for(p = temp+1;*p;p++){
        if(*p == '/'){
            *p = '\0';//这边检测到/就切换成\0，然后直接读取字符串到这里
            if(mkdir(temp,0777) !=0 && errno != EEXIST){
                return -1;
            }
            *p = '/';
        }
    }
    return mkdir(path,0777);
}

int mkDir(const char* command,Canalysis_t* anaCommand){
    bzero(anaCommand->clientCommand,anaCommand->commandLength);
    int ret = mkdir_p(command);
    if(ret == 0){    
        snprintf(anaCommand->clientCommand, anaCommand->commandLength, "创建文件夹成功：%s",command+anaCommand->homelength);
        return 0;
    }
    else{
        strerror_r(errno,anaCommand->clientCommand,anaCommand->commandLength);
        /* printf("erro message is %s\n",anaCommand->clientCommand); */
        return -1;
    }
}

int rmDir(const char* command,Canalysis_t* anaCommand){
    bzero(anaCommand->clientCommand,anaCommand->commandLength);
    int ret = rmdir(command);
    if(ret == -1){
        strerror_r(errno,anaCommand->clientCommand,anaCommand->commandLength);
        printf("erro message is %s\n",anaCommand->clientCommand);
        return -1;
    }
    else{
        
        sprintf(anaCommand->clientCommand,"删除文件夹成功");
    }
    return 0;
}

//file类的返回应该为filename,直接用结构体的lastname读取了
int putsFile(const char* command,Canalysis_t* anaCommand){
    char buffer[1024] = {0};
    strncpy(buffer,command,strlen(command)-strlen(anaCommand->lastname));
    /* printf("buffer pwd is %s\n",buffer); */
    int ret = cdDir(buffer,anaCommand);
    if(ret == -1){
        return -1;
    }
    return 0;   
}
int getsFile(const char* command,Canalysis_t* anaCommand){
    char buffer[1024] = {0};
    strncpy(buffer,command,strlen(command)-strlen(anaCommand->lastname));
    /* printf("buffer pwd is %s\n",buffer); */
    int ret = cdDir(buffer,anaCommand);
    if(ret == -1){
        return -1;
    }
    return 0;
}
int removeFile(const char* command,Canalysis_t* anaCommand){
    char buffer[1024] = {0};
    strncpy(buffer,command,strlen(command)-strlen(anaCommand->lastname));
    /* printf("buffer pwd is %s\n",buffer); */
    int ret = cdDir(buffer,anaCommand);
    if(ret == -1){
        return -1;
    }
    return 0;
}

//切割并压栈
int strtoken(char* command,dirStack_t* dstack){
    char* cname = NULL;
    /* printf("command is %s\n",command); */
    char temp[1024];
    bzero(temp,sizeof(temp));
    strcpy(temp,command);

    char* p;
    p = strtok(temp,"/");
    while(p!=NULL){
        if(strcmp(p,"..")==0){
            popDirStack(dstack,cname);
            free(cname);
            cname = NULL;
        }
        else if(strcmp(p,".")==0){

        }else{
            pushDirStack(dstack,p);
        }
        p = strtok(NULL,"/");
    };

    return 0;
}

//检查路径是否正确
int checkPath(char* nowPath,Canalysis_t* anaCommand){
    if(strlen(nowPath) < (unsigned long)anaCommand->homelength){
        return -1;
    }
    int ret = strncmp(nowPath, anaCommand->absolutePath,anaCommand->homelength);
    if(ret == 0){
        return 0;
    }
    else{
        return -1;
    }
}

//遍历切割完成的栈并变成字符串路径
int concatenateString(dirStack_t* dstack,char* result){
    dirNode_t* current = dstack->top;
    char buffer[1024] = {0};
    while(current!=NULL){
        sprintf(result,"/%s%s",current->cname,buffer);
        /* printf("result %s\n",result); */
        strcpy(buffer,result);
        current = current->next;
    }
    return 0;
}


//worler的主调函数，传入一个字符串（总命令）
//传入传出一个结构体，里面带有返回的字符串和对应的命令类型编号
int separationCommand(const char* command,Canalysis_t* anaCommand){
    //函数指针，方便快速调用
    Funcptr funcArray[] = {cdDir,lsDir,pwdDir,mkDir,rmDir,getsFile,putsFile,removeFile};
    char tag[10] = {0};
    char identifier[1024] = {0};
    int ret = sscanf(command,"%s %s",tag,identifier);
    if(ret < 1){
        sprintf(anaCommand->clientCommand,"读取出错");
        return -1;
    }
    printf("tag is %s\n",tag);
    printf("identifier is %s\n",identifier);
    /* if(identifier[0]=='\0'){ */
        /* printf("identifier is empty\n"); */
    /* } */
    chooseCommand(tag,anaCommand);
    
    dirStack_t* dstack = initDirStack();
    
    strtoken(anaCommand->clientCommand,dstack);
    
    /* print_dirstack(dstack); */

    strtoken(identifier,dstack);
    
    /* print_dirstack(dstack); */
    /* printf("result token str is %s\n",anaCommand->clientCommand); */
    
    char joint[1024] = {0};
    concatenateString(dstack,joint);
    /* printf("joint dir is %s\n",joint); */
    
    anaCommand->lastname = (char* )calloc(100,sizeof(char));
    strcpy(anaCommand->lastname,dstack->top->cname);
    /* printf("lastname is %s\n",anaCommand->lastname); */

    destoryDirStack(dstack);
    free(dstack);
    dstack = NULL;

    ret = checkPath(joint,anaCommand);
    if(ret == 0){
        /* printf("路径正确\n"); */
        int result = funcArray[anaCommand->flag - 1](joint,anaCommand);
        if(result == -1){
            return -1;
        }
        /* printf("ana result return is %s\n",anaCommand->clientCommand); */
    }
    else{
        bzero(anaCommand->clientCommand,anaCommand->commandLength);
        sprintf(anaCommand->clientCommand,"不能超出用户空间");
        return -1;     
    }

    return 0;
}


//一键free，仅限初始化堆空间使用
int freeCanalysis(Canalysis_t* anaCommand){
    free(anaCommand->clientCommand);
    free(anaCommand->absolutePath);
    free(anaCommand->lastname);

    return 0;
}

//一键初始化，后续可更该里面的固定地址空间
int initCanalysis(Canalysis_t* command){
    char orgin_path[1024] = "/root/group_work/cpp65-file-server/server/user_dir";
    chdir(orgin_path);
    bzero(command,sizeof(Canalysis_t));
    command->commandLength = 4096;
    command->clientCommand = (char*)calloc(command->commandLength,sizeof(char));
    getcwd(command->clientCommand,command->commandLength);
    command->homelength = strlen(orgin_path);
    command->absolutePath = (char*)calloc(command->homelength+1,sizeof(char));
    sprintf(command->absolutePath,"%s",orgin_path);

    return 0;
}

/* //范例 */
/* int main(){ */
/*     Canalysis_t command; */
    
/*     initCanalysis(&command); */
/*     /1* bzero(&command,sizeof(command)); *1/ */
/*     /1* command.commandLength = 4096; *1/ */
/*     /1* command.clientCommand = (char*)calloc(command.commandLength,sizeof(char)); *1/ */
/*     /1* getcwd(command.clientCommand,command.commandLength); *1/ */
/*     /1* char absolutePath[] = "/home/chaos/homework/git-practice/linux-practice"; *1/ */
/*     /1* command.homelength = strlen(absolutePath); *1/ */
/*     /1* command.absolutePath = (char*)calloc(command.homelength,sizeof(char)); *1/ */
/*     /1* sprintf(command.absolutePath,"%s",absolutePath); *1/ */
/*     printf("now pwd is %s\n",command.clientCommand); */

/*     char p[] = "cd 5.5"; */
/*     separationCommand(p,&command); */
    
/*     printf("final result is %s\n",command.clientCommand); */

/*     printf("--------------------------\n"); */

/*     bzero(command.clientCommand,command.commandLength); */
/*     getcwd(command.clientCommand,command.commandLength); */
/*     char p2[] = "pwd"; */
/*     separationCommand(p2,&command); */
/*     printf("pwd is %s\n",command.clientCommand); */

/*     printf("--------------------------\n"); */

/*     bzero(command.clientCommand,command.commandLength); */
/*     getcwd(command.clientCommand,command.commandLength); */
/*     char p3[] = "mkdir dir3"; */
/*     separationCommand(p3,&command); */

/*     printf("--------------------------\n"); */
/*     bzero(command.clientCommand,command.commandLength); */
/*     getcwd(command.clientCommand,command.commandLength); */
/*     char p4[] = "rmdir dir3"; */
/*     separationCommand(p4,&command); */
/*     printf("--------------------------\n"); */
/*     bzero(command.clientCommand,command.commandLength); */
/*     getcwd(command.clientCommand,command.commandLength); */
/*     char p5[] = "gets filename1"; */
/*     separationCommand(p5,&command); */
    
    
/*     free(command.clientCommand); */

/*     return 0; */
/* } */
